import 'dart:io';
import 'dart:typed_data';
import 'package:animation_effect_demo/src/effects/base/base_effect.dart';
import 'package:animation_effect_demo/src/effects/text_operation.dart';
import 'package:flutter/material.dart';

import '../utils/color_utils.dart';
import 'base/base_text_animation_effect.dart';

import 'package:image/image.dart' as img;

import 'effect_template.dart';
class TextAnimationEffect extends BaseTextAnimationEffect {

  Size? _textSize;

  @override
  EffectType get effectTyp => EffectType.textEffect;

  @override
  int get frameDuration => 50;


  double get mappingWidth =>  size.width;

  double get mappingHeight =>  size.height;


  @override
  Future<List<List<List<Color>>>> getFrames({EffectOperation? operation}) async {
    TextOperation textOperation = operation!.textOperation!;

    int ledWidth = mappingWidth.toInt();
    int ledHeight = mappingHeight.toInt();

    String content = textOperation.textStyleData.content;
    if (content.isEmpty) {
      content = ' ';
    }

    Color fontColor;
    if (textOperation.textAttrData.fontColors.length > 1) {
      fontColor = Colors.white;
    } else {
      fontColor = textOperation.textAttrData.fontColors.first;
    }
    String fontFamily = textOperation.textStyleData.fontStyle;

    final color = Platform.isIOS && fontFamily == 'Poppins'?Colors.red:fontColor;

    final fontSize = textOperation.textStyleData.fontSize;
    final backgroundColor = textOperation.textAttrData.backgroundStyle?.backgroundColor??Colors.transparent;


    int textWidth;
    int textHeight;
    Uint8List textData;
    img.Image? textImg;
    // if(Platform.isAndroid || Platform.isIOS){
    //   var nativeFontData = NativeFontData();
    //   var pngData = (await nativeFontData.getTextData(content,fontFamily: fontFamily,fontSize: fontSize,fontColor: color))!;
    //   // if(Platform.isIOS){
    //   //   textData = pngData.data;
    //   // }else{
    //   textImg = img.decodeImage(pngData.data)!;
    //     textData = textImg.buffer.asUint8List();
    //   // }
    //
    //   textWidth = textImg.width;
    //   textHeight = textImg.height;
    //
    // }else{
      final textDataInfo = await getTextData(text: content, color: color, fontSize: fontSize.toDouble(),fontFamily: textOperation.textStyleData.fontStyle);
      textWidth = textDataInfo.width;
      textHeight = textDataInfo.height;
      textData = textDataInfo.data;

      textImg = img.decodeImage(textData);
    // }

    if(textImg == null){
      return [];
    }

    _textSize = Size(textWidth.toDouble(), textHeight.toDouble());
    var animationType = textOperation.textEffectData.animationType;

    int columCount = _textSize!.width.toInt();
    int columnOffset = 0;
    if (columCount < ledWidth &&
        (animationType != AnimationType.left &&
            animationType != AnimationType.right)) {
      columnOffset = (ledWidth - columCount) ~/ 2;
      columCount = ledWidth;
    }

    ///当动效为闪烁和固定并且文字高度小于屏灯高度时，文字需要垂直居中
    int rowCount = textHeight;
    int rowOffset = 0;

    if (rowCount < ledHeight &&
        (animationType != AnimationType.up &&
            animationType != AnimationType.down)) {
      rowOffset = (ledHeight - rowCount) ~/ 2;
      rowCount = ledHeight;
    }
    final List<List<Color>> frameData = List.generate(
        columCount, (index) => List.filled(rowCount, backgroundColor));


    for (int y = 0; y < textHeight; y++) {
      for (int x = 0; x < textWidth; x++) {
        var pixel = textImg.getPixelSafe(x, y);
        if(pixel.a>0){
          frameData[x + columnOffset][y + rowOffset] = Color.fromARGB(
              pixel.a.toInt(),
              pixel.r.toInt(),
              pixel.g.toInt(),
              pixel.b.toInt());
        }
      }
    }

    ///增加重复平铺时文字间距
    frameData.insert(0, List.filled(rowCount, backgroundColor));
    frameData.add(List.filled(rowCount, backgroundColor));

    return getAnimationFrames(frameData, textOperation);
  }

  List<List<List<Color>>> getAnimationFrames(List<List<Color>> textContent,TextOperation textOperation){
    int textWidth = textContent.length;
    int textHeight = textContent.first.length;
    int ledWidth = mappingWidth.round();
    int ledHeight = mappingHeight.round();
    var fontColors = textOperation.textAttrData.fontColors;
    final animationType = textOperation.textEffectData.animationType;
    var isGradientColor = fontColors.length>1;
    List<Color> gradientColors = [];
    if(isGradientColor){
      List<double> stops = List.generate(fontColors.length, (index) => index*(ledWidth/(fontColors.length-1)));
      gradientColors = List.generate(ledWidth, (index) => ColorUtils.lerpGradient(fontColors, stops, index.toDouble()));
    }

    List<List<List<Color>>> frameList = [];
    if (animationType == AnimationType.flicker) {
      int frameCount = 2;
      for (int i = 0; i < frameCount; i++) {
        if (i % 2 == 0) {
          List<List<Color>> frameData = [];
          for (int j = 0; j < ledWidth; j++) {
            List<Color> columnList = [];
            for (int k = 0; k < ledHeight; k++) {
              if (k < textHeight) {
                Color color = textContent[j % textWidth][k];
                if(isGradientColor){
                  if(color.alpha != 0){
                    color = gradientColors[j];
                  }
                }
                columnList.add(color);

              } else {
                columnList.add(Colors.transparent);
              }
            }
            frameData.add(columnList);
          }
          frameList.add(frameData);
        } else {
          frameList.add(List.filled(
              ledWidth, List.filled(ledHeight, Colors.transparent)));
        }
      }
    } else if (animationType == AnimationType.left) {
      int frameCount = textWidth;
      for (int i = 0; i < frameCount; i++) {
        List<List<Color>> frameData = [];
        for (int j = 0; j < ledWidth; j++) {
          List<Color> columnList = [];
          for (int k = 0; k < ledHeight; k++) {
            Color color = textContent[(j + i) % textWidth][k % textHeight];
            if(isGradientColor){
              if(color.alpha != 0){
                color = gradientColors[j];
              }
            }
            columnList.add(color);
          }
          frameData.add(columnList);
        }
        frameList.add(frameData);
      }
    } else if (animationType == AnimationType.up) {
      int frameCount = textHeight;
      for (int i = 0; i < frameCount; i++) {
        List<List<Color>> frameData = [];
        for (int j = 0; j < ledWidth; j++) {
          List<Color> columnList = [];
          for (int k = 0; k < ledHeight; k++) {

            Color color = textContent[j % textWidth][(k + i) % textHeight];
            if(isGradientColor){
              if(color.alpha != 0){
                color = gradientColors[j];
              }
            }
            // if(brightness!= 100){
            //   var hsvColor = HSVColor.fromColor(color);
            //   color = hsvColor.withValue(hsvColor.value * brightness * 0.01).toColor();
            // }
            columnList.add(color);
          }
          frameData.add(columnList);
        }
        frameList.add(frameData);
      }
    } else {
      List<List<Color>> frameData = [];
      for (int j = 0; j < ledWidth; j++) {
        List<Color> columnList = [];
        for (int k = 0; k < ledHeight; k++) {
          Color color = textContent[j % textWidth][k];
          if(isGradientColor){
            if(color.alpha != 0){
              color = gradientColors[j];
            }
          }
          columnList.add(color);
        }
        frameData.add(columnList);
      }
      frameList.add(frameData);
    }
    return frameList;
  }

  @override
  Size get size => const Size(24, 24);
}
